/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include <map>
#include "Mesh.h"

#include <字符串数值互换.h>


enum E_笔刷类型 {
	e_单色填充,
	e_单色描边,
	e_单色边面,
	e_圆公切链接线,
	e_单色纹理,
	e_纹理,
	e_多纹理,
	e_条纹,
	e_色轮,
	e_渐变,
	e_噪波,
};

enum class E_纹理用途布局 {
	e_采样,
	e_帧附件,
};

struct S_Widget预设凸包图元 {
	static uvec2	m_矩形;
	static uvec2	m_左圆角矩形;
	static uvec2	m_右圆角矩形;

	static uvec2	m_上圆角矩形;
	static uvec2	m_下圆角矩形;
	static uvec2	m_圆角矩形;
	static uvec2	m_左上圆角矩形;
	static uvec2	m_右上圆角矩形;
	static uvec2	m_圆形;

	static uvec2	m_竖向圆角连接线;
	static uvec2	m_横向圆角连接线;
	static uvec2	m_竖向斜角连接线;
	static uvec2	m_横线;
	static uvec2	m_竖线;
	static uvec2	m_斜线;
	static uvec2	m_生成C形左拐角连接线;
	static uvec2	m_生成C形右拐角连接线;
	static uvec2	m_生成L形下拐角连接线;
	static uvec2	m_生成L形上拐角连接线;
};


typedef struct {
	float32 m_间距;
	E_方向	m_方向;
}S_行字符串绘制属性;

typedef struct {
	float32 m_字号;
	float32 m_行距;
	float32 m_间距;
	E_方向	m_方向;
}S_字符串绘制属性;

typedef struct {
	vec2	begin_coord;
	vec2	control_coord;
	vec2	end_coord;
	float32	radius;				//线端圆弧半径
	float32 link_successively;	//线连接循序  从输出到输入或从输入到输出
}S_连接线坐标参数;

typedef struct {
	mat3X2*	coord;
	uint32* color;
	int32*	text;
	bool	GPU参数重置;
}S_sf_文字GPU参数映射;

typedef struct {
	mat3X2* p变换;
	uvec2*	p图元;
	uint32* p颜色;
	bool	GPU参数重置;
}S_sf_单色GPU映射;

typedef struct {
	mat3X2*	pCoord;
	uint32*	pColor;
	uint32*	pICO_UV;
}S_sf_图标GPU映射;


struct S_2D颜色包 {
	S_RGBA8UI	m_颜色;
	uint8		m_模糊;
	uint8		m_阴影;
	uint8		m_模式;
	uint8		m_保留;

	S_2D颜色包(S_RGBA8UI 颜色, uint8 模糊, uint8 阴影, uint8 模式) {
		m_颜色 = 颜色;
		m_模糊 = 模糊;
		m_阴影 = 阴影;
		m_模式 = 模式;
		m_保留 = 0;
	}
	S_2D颜色包(S_RGBA8UI 颜色) {
		m_颜色 = 颜色;
		m_模糊 = 0;
		m_阴影 = 0;
		m_模式 = 0;
		m_保留 = 0;
	}
	S_2D颜色包() {
		m_颜色 = {0,0,0,0};
		m_模糊 = 0;
		m_阴影 = 0;
		m_模式 = 0;
		m_保留 = 0;
	}

	operator uvec2 () {
		return { f_PackData4X8(m_颜色), uint32(m_模糊) | (m_阴影<<8) | (m_模式<<16)};
	}
};



struct S_PolygonDataGroup {
	std::unordered_map<std::string, std::vector<S_2D_EffectLinearGradient>>	渐变颜色;
	std::unordered_map<std::string, S_2D渐变控制>							效果控制;

	std::vector<PolygonData>	graph;
	vec2						bound;
	vec2						minBound;
	vec2						maxBound;

};

struct S_矢量图形构建参数 {
	S_PolygonDataGroup					m_路径数据;
	
	std::vector<std::vector<uint32>>	m_polygon_轮廓路径;
	std::vector<std::vector<uint32>>	m_polygon_三角形;
	std::vector<std::vector<mat2>>		m_polygon_路径顶点;

	std::map<std::string, uint32>			m_渐变颜色键值;
	std::map<std::string, uint32>			m_效果控制键值;
	
	std::vector<S_2D_EffectLinearGradient>	m_polygon_渐变颜色;
	std::vector<S_2D_EffectControl>			m_polygon_效果控制;

	std::vector<S_2D图元属性>				m_图元属性;

	std::u16string name;
};

struct S_矢量图形几何元素 {
	std::vector<S_GPU内存块> m_矢量图像坐标;
	std::vector<S_GPU内存块> m_矢量图像索引;
	std::vector<S_GPU内存块> m_矢量图像轮廓;

	std::vector<S_GPU内存块>	m_效果控制;
	S_GPU内存块					m_渐变颜色;

	std::vector<uint32>			m_效果控制内存偏移;
	std::vector<S_2D图元属性>	m_图元属性;
};








struct S_Surface {
	S_Surface();
	void		f_Draw点();
};
typedef void(*f_Draw_Surface3D)(S_设备环境& ctx);


typedef struct S_Frame2D {
	S_帧缓存*		m_帧缓存;
	S_纹理*			m_Color[2];
	S_纹理*			m_Depth;
	S_纹理采样器*	m_纹理采样器;
}S_Frame2D;



S_Surface3D*	f_surface_Create(S_设备环境& Ctx3D, const uvec2& size, bool 多重采样, bool 创建单层输出 = false, bool 阴影 = false);
S_Surface3D*	f_surface3D_创建(S_设备环境& Ctx3D, uvec2 size, E_MS次数 采样次数);
void			f_surface3D_重置大小(S_Surface3D* surf, uvec2 size);

S_Frame2D* f_surface_创建平面帧(S_设备环境& ctx, const uvec2& size);
void f_surface_销毁平面帧(S_Frame2D* face);
void f_surface_重置平面帧大小(S_设备环境& ctx, S_Frame2D* face, const uvec2& size);


bool			f_surface_改变大小(S_Surface3D* face, const uvec2& size, bool 创建单层输出 = false);
void			f_surface_set采样(S_Surface3D* face, E_MS次数 采样);

void			f_surface_创建G缓存(S_Surface3D* face);

S_Surface3D*	f_surface_CreateCube(S_设备环境& Ctx3D, uvec2 size, uvec2 渲染大小, S_纹理采样器* 采样器, uint8 层级数量);
bool			f_surface_Cube改变大小(S_Surface3D* face, uvec2 size);
bool			f_surface_3D改变大小(S_Surface3D* face, uvec2 size);

S_Surface3D*	f_surface_Create几何缓存(S_设备环境& Ctx3D, const uvec2& size);
bool			f_surface_set几何缓存分辨率(S_Surface3D* face, uvec2 size);

bool			f_surface_set渲染纹理(S_Surface3D* face, uint32 内部纹理ID);


void			f_surface_setG缓存纹理大小(S_Surface3D* face, uvec2 size);

void			f_surface_Release(S_Surface3D* face);
void			f_surface_改变纹理用途(S_Surface3D* face, E_纹理用途布局 用途);




typedef void(*fp_Surface2D元素变换属性)(void* v, uint32 num);

struct S_字体加载参数 {
	std::vector<suvec2>	m_编码区间;
	std::string         m_字体文件路径;
	uint16              m_字号;
	std::string         m_名称;
};



struct S_Font : public S_矢量字体 {
	S_纹理*					m_Tex;
	S_板载缓存*				m_uv偏移;
	S_GPU内存块				m_字符UV;
	std::vector<S_iRect>	m_区域;
	
	uint16					m_字号;
	std::string				m_字体名称;
	
	uint16	f_get字符宽度(wchar_t name) const {
		if (name == '\t') return m_字号 * 2;
		return m_区域[name].宽度;
	}
};

struct S_TexArrayRes {
	S_纹理* m_Tex;
	std::map<std::string, uint16> m_Name;

	uint16 operator [] (const std::string name) { return m_Name[name]; }
};



struct S_字体 {
	S_纹理* m_Tex; 
	std::map<wchar_t, S_iRect>	m_区域;
	std::map<wchar_t, vec3>		m_uv偏移;
	std::map<wchar_t, vec2>		m_字符大小;

	std::filesystem::path		m_字体文件路径;
	uint16						m_字号;


	float32	f_get字符宽度(wchar_t name) const {
		if (name == '\t') return m_字号 * 2;
		return m_区域.at(name).宽度;
	}
};







typedef struct {
	vec2 m_Scale;
	vec2 m_Offset;
	//uint32 m_顶点数量;
	int32 m_渐变数量;
	int32 m_间隔;
}S_2D_PanelAttr;









struct S_Widget绘制材质 {
	//S_材质管线* m_单色凸边形填充;
	//S_材质管线* m_单色凸边形描边;

	//S_材质管线* m_单色描边;
	S_材质管线* m_图标;
	//S_材质* m_线段;
	S_材质管线* m_多纹理;

	S_材质管线* m_行文本;
	//S_材质* m_刻度线_正常混合;
	S_材质管线* m_波形_正常混合;

	S_材质管线* m_单纹理;
	S_材质管线* m_间接单色填充;
	S_材质管线* m_间接单色描边;
	S_材质管线* m_动态线;

	S_材质管线* m_曲线点;
	S_材质管线* m_曲线;
	S_材质管线* m_色轮;
	S_材质管线* m_渐变;
	S_材质管线* m_多曲线;


	
	

	//S_材质管线* m_点控渐变填充;
	
	S_材质管线* m_矢量线;
	S_材质管线* m_表格线;

	S_材质管线* m_过程纹理填充;
	S_材质管线* m_外部纹理描边;
	S_材质管线* m_外部纹理填充;

	S_材质管线* m_公切园链接线;
	S_材质管线* m_连接点笔;
	S_材质管线* m_临时连接线笔;
	S_材质管线* m_单色图标笔刷;
	S_材质管线* m_纯纹理图标笔刷;
	S_材质管线* m_文本笔刷;
	S_材质管线* m_文本块笔刷;
	S_材质管线* m_边缘阴影;



	//S_材质管线* m_条纹笔刷材质;
	//S_材质管线* m_条纹填充;
	//S_材质管线* m_棋盘格填充;
	//S_材质管线* m_网格填充;
	//S_材质管线* m_渐变背景纹理填充;
	//S_材质管线* m_棋盘格背景纹理填充;


	S_材质管线* m_刻度线;
	S_材质管线* m_网格刻度线;
	//S_材质* m_表格线;

	S_纹理采样器* m_采样器;

	std::map<std::string, S_TexArrayRes>	m_ICOs;
	std::map<std::string, S_Font>			m_Fonts;

	//S_GPU纹理参数槽 m_图标纹理槽;
	
	S_Widget绘制材质(S_设备环境& Ctx, E_MS次数 msCount);
	~S_Widget绘制材质();

};




struct S_UI渲染环境 {
	S_设备环境			m_Ctx;
	S_Widget绘制材质*	m_Mat;
	E_MS次数			m_采样数;
	float32				m_DPI;
	float32				m_窗口DPI;

	S_UI渲染环境(S_设备环境& ctx, E_MS次数 msCount);
	~S_UI渲染环境();

	S_GPU纹理参数槽	m_纹理槽;

	S_纹理集*		m_平面绑定纹理集;
	S_纹理集*		m_方体绑定纹理集;

	uint32	f_Bind_纹理(S_纹理* tex);
	void	f_UpBind_纹理(S_纹理* tex);
	void	f_update_纹理绑定();


	S_板载缓存*						m_层区域属性;
	std::vector<S_FrameSample_TAA>	m_层区域采样属性;

	//C_DescriptorSet*	m_DS_合成;
	S_2D画布*			m_合成画布;
	C_DescriptorSet*	m_DS_UI图层纹理混合;

	struct C_Widget管理*	m_GM;


	void f_渲染图层混合(std::vector<mat2>& vert);
	void f_准备图层渲染();
	



	//废弃
	uint16		m_文字字号;
	static void f_初始化预设图元();
	static void f_销毁绘图资源();

	static S_Widget预设凸包图元      m_图元ID;
	static std::vector<S_2D图元顶点> m_预设图元顶点;

private:
	bool m_更新纹理绑定;
};





typedef void(*fp_Surface2D参数设置回调)(S_设备环境& ctx, struct _S_Surface2D& surf);
typedef void(*fp_Surface2D绘制参数设置)(struct S_2D画布* 画布, struct _S_Surface2D* surf, S_板载缓存* mat);
typedef void(*fp_Surface2D参数销毁)(struct _S_Surface2D* surf);

typedef struct _S_Surface2D {
	S_GPU内存块  m_间接;
	S_GPU内存块  m_2D层;
	S_GPU内存块  m_平面形状;
	S_GPU内存块  m_元素变换;
	S_GPU内存块  m_元素颜色;

	S_GPU内存块* m_画布变换;
	S_GPU内存块* m_自定义属性;

	S_元素绘制类型 m_绘制类型;
	

	S_管线槽	m_多维材质槽;
	void*		m_自定义属性参数;

	S_推送常量	m_常量推送;

	fp_Surface2D参数设置回调	mf_参数设置回调;

	

	S_GPU纹理参数槽 m_纹理槽;
	S_矢量字体*		m_字体;
	float32			m_线宽;

	bool m_间接引用;
	bool m_填充面;

	uint32	m_实例数量;
	uint32	m_实例偏移;
	uint32	m_顶点数量;
	uint32	m_顶点偏移;

	bool	m_顶点引用;
	bool	m_索引引用;

	fp_Surface2D绘制参数设置	mf_绘制参数设置;
	fp_Surface2D参数销毁		mf_销毁自定义参数;





	//废弃
	std::string	m_纹理;
	S_2D笔刷	m_笔刷;
	S_GPU内存块	m_顶点;
	S_GPU内存块	m_索引;

}S_Surface2D;






struct S_2D画布 {
	S_设备环境			m_Ctx;
	
	bool						m_是否重绘;

	//外部创建由外部释放
	std::vector<S_Surface2D*>	m_绘制元素;
	S_GPU内存块					m_变换;

	S_2D画布(S_设备环境& ctx);
	~S_2D画布();



	//virtual void f_绘制到屏幕(S_渲染参数& 参数);
	void	f_清除绘制数据();

	operator S_设备环境& () {
		return m_Ctx;
	}




	//废弃
	S_Widget绘制材质*		m_调色板;

	//static S_板载缓存*	m_间接绘制图元顶点;
	//static S_板载缓存*       g变换GPU缓存;
	//static S_板载缓存*       g行文本变换GPU缓存;
	//static S_板载缓存*       g行文本颜色GPU缓存;

	static S_板载缓存*       g字符GPU缓存;
	

	static S_板载缓存*       g表格变换GPU缓存;
	static S_板载缓存*       g表格颜色GPU缓存;

	static S_板载缓存*       g凸包变换;
	static S_板载缓存*       g凸包颜色;
	static S_板载缓存*       g凸包线属性;
	static S_板载缓存*       g凸包纹理属性;
	static S_板载缓存*       g凸包渐变属性;
	static S_板载缓存*       g凸包渐变控制属性;
	static S_板载缓存*       g凸包色轮属性;
	static S_板载缓存*       g图标变换;
	static S_板载缓存*       g图标颜色;
	static S_板载缓存*       g纹理变换;
	static S_板载缓存*        g线段;

	int16						m_绘制推进层;
	std::vector<S_Surface2D>	m_surf;
	S_板载缓存*					m_父级画布属性;
	std::vector<S_板载缓存*>	m_属性;
	std::vector<S_板载缓存*>	m_扩展GPU参数;

	static S_GPU内存块		g预设_矩形;
	static S_GPU内存块		g预设_圆形;
	static S_GPU内存块		g预设_圆角矩形;
	static S_GPU内存块		g预设_左圆角矩形;
	static S_GPU内存块		g预设_右圆角矩形;
	static S_GPU内存块		g预设_上圆角矩形;
	static S_GPU内存块		g预设_下圆角矩形;
	static S_GPU内存块		g预设_左上圆角矩形;
	static S_GPU内存块		g预设_右上圆角矩形;
	static S_GPU内存块		g预设_左下圆角矩形;
	static S_GPU内存块		g预设_右下圆角矩形;

};



inline void f_initSurface2D(S_Surface2D* face, S_设备环境& m_Ctx) {
	face->m_顶点 = f_bm_alloc(f_buf_getGlobal().g顶点, 0);
	face->m_索引 = f_bm_alloc(f_buf_getGlobal().g索引, 0);
	face->m_间接 = f_bm_alloc(f_buf_getGlobal().g间接, 0);
	face->m_2D层 = f_bm_alloc(f_buf_getGlobal().g2D层, 0);

	face->m_顶点引用 = false;
	face->m_索引引用 = false;
	face->m_间接引用 = false;

	face->m_自定义属性参数 = nullptr;
	face->mf_绘制参数设置 = nullptr;
	face->mf_销毁自定义参数 = nullptr;

	face->m_常量推送 = {};

	face->m_填充面 = true;

	face->m_纹理槽 = {};

	face->m_笔刷 = {};
	
	face->m_线宽 = 0.0;
	face->m_顶点数量 = 0;
	face->m_顶点偏移 = 0;
	face->m_实例数量 = 0;
	face->m_实例偏移 = 0;
	
	f_me_init材质槽(&face->m_多维材质槽, 1);
}

void f_surface2D_release(S_Surface2D* face);

Inline S_Surface2D* f_surface2D_alloc(S_设备环境& ctx) {
	S_Surface2D* surf = (S_Surface2D*)malloc(sizeof(S_Surface2D));
	f_initSurface2D(surf, ctx);
	return surf;
}

void f_surface_创建2D绘制预设形状缓存(S_设备环境& ctx);
void f_surface_销毁2D绘制预设形状缓存(S_设备环境& ctx);

void		f_alloc_笔刷槽数量(S_2D笔刷& 笔刷, uint32 num);


void		f_surface_加载字体(S_UI渲染环境& ctx, const S_字体加载参数& 字体参数);
void		f_surface_加链字体纹理(S_设备环境& ctx, S_字体& 字体, const S_字体加载参数& 字体参数, const std::u16string& txt);


uint16		f_surface_get字符串宽度T(const S_Font& font, std::u16string text, float32 gap);
uint16		f_surface_get字符串宽度(const S_Font& font, std::u16string text, float32 gap);
uint16		f_surface_get字符串宽度(const S_Font& font, wchar_t text, float32 gap);


inline const S_Font&	f_surface_get字体库(S_UI渲染环境& ctx, std::string name) {
	name += "_" + f_整数值转字符串(ctx.m_文字字号);
#ifdef _DEBUG  

#endif
	if (name == "晴圆等宽_12") {
		ctx.m_Mat->m_Fonts;
	}
	if (ctx.m_Mat->m_Fonts.find(name) == ctx.m_Mat->m_Fonts.end()) {
		return ((ctx.m_Mat->m_Fonts.begin()->second));
	}
	
	return ctx.m_Mat->m_Fonts[name];
}

inline const S_Font& f_surface_get字体库(S_UI渲染环境& ctx, std::string name, std::string 字号) {
	name += "_" + 字号;
#ifdef _DEBUG  
	if (name == "晴圆等宽_12") {
		ctx.m_Mat->m_Fonts;
	}
	if (ctx.m_Mat->m_Fonts.find(name) == ctx.m_Mat->m_Fonts.end()) {
		return ((ctx.m_Mat->m_Fonts.begin()->second));
	}
#endif
	return ctx.m_Mat->m_Fonts[name];
}

Inline const S_Font& f_surface_get字体(S_UI渲染环境& ctx, std::string name) {
	name += "_" + f_整数值转字符串(ctx.m_文字字号);
#ifdef _DEBUG  
	if (name == "晴圆等宽_12") {
		ctx.m_Mat->m_Fonts;
	}
	if (ctx.m_Mat->m_Fonts.find(name) == ctx.m_Mat->m_Fonts.end()) {
		return ((ctx.m_Mat->m_Fonts.begin()->second));
	}
#endif
	return ctx.m_Mat->m_Fonts[name];
}

Inline const S_Font& f_surface_get字体(S_2D画布* 画布, std::string name, uint32 字号) {
	name += "_" + f_整数值转字符串(字号);
#ifdef _DEBUG 
	if (name == "晴圆等宽_12") {
		画布->m_调色板->m_Fonts;
	}
	if (画布->m_调色板->m_Fonts.find(name) == 画布->m_调色板->m_Fonts.end()) {
		return ((画布->m_调色板->m_Fonts.begin()->second));
	}
#endif
	return 画布->m_调色板->m_Fonts[name];
}


//#define DEF_IDget笔刷(画布, ID)  (画布)->m_笔刷[(ID)]




uint32 f_mesh_gen网格元素绘制属性(S_Mesh* mesh, uint32 num);
uint32 f_mesh_resize间接绘制网格属性(S_Mesh* mesh, uint32 num);
void f_mesh_set网格元素绘制属性(S_Mesh* mesh, const S_MeshTranformProp& prop, uint32 offset = 0);
void f_mesh_set绘制内存属性(S_Mesh* mesh, const S_Vert_MeshDrawProp& prop);
void f_mesh_gen绘制内存属性_文本(S_Mesh* mesh, const S_ShaderConst_TextAttr& prop);

//bool f_surface_Gpu射线拾取网格_坐标_法线_UV(S_Mesh* mesh, const Mat44f& mat, float32 独立缩放, const vec3& s, const vec3& dir, vec3& 交点, float32& min距离);






/*typedef struct {
S_设备环境*	m_Ctx;
S_帧缓存*	m_帧缓存;

S_纹理*		m_Color[6];
S_纹理*		m_Depth[6];
//S_纹理采样器*	m_Smaple;
//S_纹理*		m_GBuffer[2];
uint32		m_纹理数量;
uint32		m_G缓存数量;
uint8		m_交换ID;

}S_Surface3D;*/


//typedef struct {
//	mat3X2* coord;
//	uvec2* p图元;
//	uint32* pEColor;
//	uint32* pColor;
//	bool	GPU参数重置;
//}S_sf_单色边面GPU映射;

//typedef struct {
//	mat3X2* pCoord;
//	uvec2* p图元;
//	uvec2* pColor;
//	bool	GPU参数重置;
//}S_sf_纹理面GPU映射;


